//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include <ddk.h>
#include <nu_api.h>
#include <zenr_api.h>
#include "_sprintf.h"

#define MDT_AUDIOLOOPBACKTEST              0
#define MDT_SDTEST                         1
#define MDT_ENGR_GSMMAXPOWER               2
#define MDT_KEYLED_ON                      3
#define MDT_KEYLED_OFF                     4
#define MDT_KEYPADLEDLEVEL                 5
#define MDT_BACKLIGHT_ON                   6
#define MDT_BACKLIGHT_OFF                  7
#define MDT_LCDBACKLIGHT_LEVEL             8
#define MDT_SEARCH_BT_DEVICE               10
#define MDT_USB_MASS                       0x10
#define MDT_GET_VERSOIN                    0x11


#define MDT_T_MODEM_EM                      0x20

EmIsrParameter Param;

class CMdt : public CDeviceDriver {
public:
    CARAPI Read(
        /* [in] */ Int64 u64Offset,
        /* [in] */ Int32 bytesToRead,
        /* [out] */ MemoryBuf * pBuffer,
        /* [out] */ IEvent * * ppCompletionEvent);

    CARAPI Write(
        /* [in] */ Int64 u64Offset,
        /* [in] */ const MemoryBuf & buffer,
        /* [out] */ Int32 * pBytesWritten,
        /* [out] */ IEvent * * ppCompletionEvent);

    CARAPI Control(
        /* [in] */ Handle32 nControlCode,
        /* [in] */ const MemoryBuf & inBuffer,
        /* [out] */ MemoryBuf * pOutBuffer,
        /* [out] */ IEvent * * ppCompletionEvent);

    virtual void Dispose(){}
    ECode MDTMgmThread(void *arg);
    ECode InitLightSensorEventQueue();

public:
    DzEvent m_LightSensorEvent;
};

CMdt *g_pMdt = NULL;

extern "C" void LightSensorCallBack(Uint16 adc3value)
{
    Param.nParameter1 = adc3value;
	nu_notifyDeviceCaller((Int32)&(g_pMdt->m_LightSensorEvent), SIGNALED);
}

ECode CMdt::MDTMgmThread(void *arg)
{
    WaitResult wr;

    while (1) {
        m_LightSensorEvent.Wait(&wr, NULL);
        MemoryBuf eventData ((Byte *)&Param, sizeof(EmIsrParameter));
        EmPostEvent(888, eventData);
    }
    return NOERROR;
}

ECode MDTThreadRoutine(void *arg)
{
    g_pMdt->MDTMgmThread(NULL);
    return NOERROR;
}

ECode CreateMDTThread()
{
    ECode ec;
    ec = DzCreateKernelThread(MDTThreadRoutine,
        (PVoid)NULL, CreateThreadFlag_System, ThreadPriorityRank_Normal, NULL);
    if (FAILED(ec)) {
        kprintf("unable to create ctrl thread ec : %08x\n", ec);
        return ec;
    }
    kprintf("Create Light Sensor Management Thread Succeeded!\n");
    return ec;
}

ECode CMdt::Read(
    /* [in] */ Int64 u64Offset,
    /* [in] */ Int32 bytesToRead,
    /* [out] */ MemoryBuf * pBuffer,
    /* [out] */ IEvent * * ppCompletionEvent)
{
    return E_NOT_IMPLEMENTED;
}

ECode  CMdt::Write(
    /* [in] */ Int64 u64Offset,
    /* [in] */ const MemoryBuf &buffer,
    /* [out] */ Int32 * pBytesWritten,
    /* [out] */ IEvent * * ppCompletionEvent)
{
    return E_NOT_IMPLEMENTED;
}

ECode CMdt::Control(
    /* [in] */ Handle32 nControlCode,
    /* [in] */ const MemoryBuf &inBuffer,
    /* [out] */ MemoryBuf * pOutBuffer,
    /* [out] */ IEvent * * ppCompletionEvent)
{
    switch (nControlCode) {
        case MDT_AUDIOLOOPBACKTEST: {
            if (inBuffer.GetCapacity() < 8) return E_INVALID_ARGUMENT;
            int *p = (int *)inBuffer.GetPayload();
            zapi_MDT->AudioLoopbackTest(p[0], p[1]);
            break;
        }
        case MDT_SDTEST: {
            if (inBuffer.GetCapacity() < 8) return E_INVALID_ARGUMENT;
            int *p = (int *)inBuffer.GetPayload();
            zapi_MDT->SDTest(p[0], p[1]);
            break;
        }
        case MDT_ENGR_GSMMAXPOWER: {
            if (inBuffer.GetCapacity() < 4) return E_INVALID_ARGUMENT;
            int *p = (int *)inBuffer.GetPayload();
            zapi_MDT->Engr_GSMMaxPower(p[0]);
            break;
        }
        case MDT_KEYLED_ON: {
            zapi_HMI->KeypadLED_On();
            break;
        }
        case MDT_KEYLED_OFF: {
            zapi_HMI->KeypadLED_Off();
            break;
        }
        case MDT_KEYPADLEDLEVEL: {
            if (inBuffer.GetCapacity() < 4) return E_INVALID_ARGUMENT;
            int *p = (int *)inBuffer.GetPayload();
            zapi_HMI->KeypadLED_Level(p[0]);
            break;
        }
        case MDT_BACKLIGHT_ON: {
            zapi_HMI->LcdBacklight_On();
            break;
        }
        case MDT_BACKLIGHT_OFF: {
            zapi_HMI->LcdBacklight_Off();
            break;
        }
        case MDT_LCDBACKLIGHT_LEVEL: {
            if (inBuffer.GetCapacity() < 4) return E_INVALID_ARGUMENT;
            if (pOutBuffer == NULL || pOutBuffer->GetCapacity() < 4) return E_INVALID_ARGUMENT;
            int *p = (int *)inBuffer.GetPayload();
            UInt32 ret = zapi_HMI->LcdBacklight_Level(p[0]);
            pOutBuffer->Copy((Byte *)&ret, 4);
            pOutBuffer->SetUsed(4);
            break;
        }

        case MDT_USB_MASS:
            int bUartMode;
            bUartMode = *(int *)inBuffer.GetPayload();
            zapi_MDT->Usb_Mass(bUartMode);
            break;
        case MDT_T_MODEM_EM:
            T_MODEM_EM idx;
            idx = *(T_MODEM_EM *)inBuffer.GetPayload();
            zapi_MDT->T_Modem_Em((T_MODEM_EM)idx, (char *) pOutBuffer->GetPayload());
            break;
        case MDT_GET_VERSOIN: {
            if (inBuffer.GetCapacity() < 4 || pOutBuffer == NULL) return E_INVALID_ARGUMENT;
            UInt32 inData = *((UInt32 *)inBuffer.GetPayload());
            const char *str = NULL;
            switch (inData) {
                case 1:
                    str = zapi_MDT->GetFIHSwVersion();
                    strncpy((char *)pOutBuffer->GetPayload(), str, pOutBuffer->GetCapacity());
                    break;
                case 2:
                    str = zapi_MDT->GetFIHHwVersion();
                    strncpy((char *)pOutBuffer->GetPayload(), str, pOutBuffer->GetCapacity());
                    break;
                case 3:
                    str = zapi_MDT->GetFIHSwBuildDate();
                    strncpy((char *)pOutBuffer->GetPayload(), str, pOutBuffer->GetCapacity());
                    break;
                case 4:
                    str = zapi_MDT->GetFIHSwBuildTime();
                    strncpy((char *)pOutBuffer->GetPayload(), str, pOutBuffer->GetCapacity());
                    break;
                default :
                    break;
            }
            if (NULL != str) {
                *(pOutBuffer->GetPayload() + pOutBuffer->GetCapacity() - 1) = '\0';
            }

            break;
        }
        default:
            break;
    }

    return NOERROR;
}

EXTERN IDeviceDriver * CDECL CreateMDTServer(uint_t uDeviceNo, void *pvParameter)
{
    g_pMdt = new CMdt;
    if (NULL == g_pMdt) {
        kprintf("Init Mdt Failed! Out of Memeory!\n");
        return NULL;
    }

    zapi_HMI->AddLightSensorCallback(LightSensorCallBack);
    CreateMDTThread();

    kprintf("CreateMDTServer ok\n");
    return g_pMdt;
}

